package com.wgh.demo.ai.controller;

import com.wgh.demo.ai.service.DocumentConversionService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.http.codec.multipart.FilePart;
import reactor.core.publisher.Mono;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * 文档转换控制器
 */
@RestController
@RequestMapping("/api/document")
public class DocumentConversionController {

    private static final Logger logger = LoggerFactory.getLogger(DocumentConversionController.class);
    private final DocumentConversionService documentConversionService;

    @Autowired
    public DocumentConversionController(DocumentConversionService documentConversionService) {
        this.documentConversionService = documentConversionService;
        logger.info("DocumentConversionController初始化完成");
    }

    /**
     * Word转PDF接口
     */
    @PostMapping(value = "/word-to-pdf", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public Mono<ResponseEntity<byte[]>> convertWordToPdf(@RequestPart("file") FilePart file) {
        logger.info("收到Word转PDF请求，文件名: {}", file.filename());

        // 使用ByteArrayOutputStream收集文件数据
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

        return file.content()
                .doOnEach(dataBufferSignal -> {
                    if (dataBufferSignal.hasValue()) {
                        DataBuffer dataBuffer = dataBufferSignal.get();
                        try {
                            // 直接将DataBuffer中的数据写入ByteArrayOutputStream
                            byteArrayOutputStream.write(dataBuffer.asByteBuffer().array());
                        } catch (IOException e) {
                            logger.error("写入文件数据失败: {}", e.getMessage(), e);
                        } finally {
                            // 释放DataBuffer
                            DataBufferUtils.release(dataBuffer);
                        }
                    }
                })
                .then(Mono.defer(() -> {
                    try {
                        byteArrayOutputStream.flush();
                        byte[] fileBytes = byteArrayOutputStream.toByteArray();
                        logger.info("成功读取文件数据，大小: {} 字节", fileBytes.length);

                        InputStream inputStream = new ByteArrayInputStream(fileBytes);
                        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

                        // 调用服务方法
                        return documentConversionService.convertWordToPdf(inputStream, outputStream, file.filename())
                                .map(success -> {
                                    if (success) {
                                        byte[] pdfBytes = outputStream.toByteArray();
                                        HttpHeaders headers = new HttpHeaders();
                                        headers.setContentType(MediaType.APPLICATION_PDF);
                                        headers.setContentDispositionFormData(
                                                "attachment", getPdfFileName(file.filename()));
                                        headers.setContentLength(pdfBytes.length);

                                        return ResponseEntity.ok()
                                                .headers(headers)
                                                .body(pdfBytes);
                                    } else {
                                        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                                                .body(null);
                                    }
                                });
                    } catch (IOException e) {
                        logger.error("处理文件数据失败: {}", e.getMessage(), e);
                        return Mono.just(ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                                .body(null));
                    } finally {
                        try {
                            byteArrayOutputStream.close();
                        } catch (IOException e) {
                            logger.error("关闭输出流失败: {}", e.getMessage(), e);
                        }
                    }
                }));
    }

    /**
     * 图片转PDF接口
     */
    @PostMapping(value = "/images-to-pdf", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public Mono<ResponseEntity<byte[]>> convertImagesToPdf(@RequestPart("files") List<FilePart> files) {
        logger.info("收到图片转PDF请求，文件数量: {}", files.size());

        if (files.isEmpty()) {
            return Mono.just(ResponseEntity.badRequest().body(null));
        }

        List<Mono<byte[]>> imageDataMonos = new ArrayList<>();

        // 处理每个图片文件
        for (FilePart file : files) {
            Mono<byte[]> imageDataMono = file.content()
                    .collectList()
                    .map(dataBuffers -> {
                        try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
                            dataBuffers.forEach(dataBuffer -> {
                                byte[] bytes = new byte[dataBuffer.readableByteCount()];
                                dataBuffer.read(bytes);
                                try {
                                    baos.write(bytes);
                                } catch (IOException e) {
                                    throw new RuntimeException("读取图片数据失败", e);
                                }
                            });
                            return baos.toByteArray();
                        } catch (IOException e) {
                            throw new RuntimeException("关闭流失败", e);
                        }
                    });
            imageDataMonos.add(imageDataMono);
        }

        // 等待所有图片数据准备好
        return Mono.zip(imageDataMonos, objects -> {
                    byte[][] imageDatas = new byte[objects.length][];
                    for (int i = 0; i < objects.length; i++) {
                        imageDatas[i] = (byte[]) objects[i];
                    }
                    return imageDatas;
                })
                .flatMap(imageDatas -> {
                    try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
                        // 创建输入流数组
                        final java.io.InputStream[] inputStreams = new java.io.InputStream[imageDatas.length];
                        try {
                            for (int i = 0; i < imageDatas.length; i++) {
                                inputStreams[i] = new java.io.ByteArrayInputStream(imageDatas[i]);
                            }

                            return documentConversionService.convertImagesToPdf(inputStreams, outputStream)
                                    .map(success -> {
                                        if (success) {
                                            byte[] pdfBytes = outputStream.toByteArray();
                                            HttpHeaders headers = new HttpHeaders();
                                            headers.setContentType(MediaType.APPLICATION_PDF);
                                            headers.setContentDispositionFormData("attachment", "images.pdf");
                                            headers.setContentLength(pdfBytes.length);

                                            return ResponseEntity.ok()
                                                    .headers(headers)
                                                    .body(pdfBytes);
                                        } else {
                                            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                                                    .body(null);
                                        }
                                    });
                        } catch (Exception e) {
                            logger.error("处理图片数据失败: {}", e.getMessage(), e);
                            return Mono.just(ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                                    .body(null));
                        } finally {
                            // 关闭所有输入流
                            for (java.io.InputStream stream : inputStreams) {
                                if (stream != null) {
                                    try {
                                        stream.close();
                                    } catch (IOException e) {
                                        logger.error("关闭输入流失败: {}", e.getMessage(), e);
                                    }
                                }
                            }
                        }
                    } catch (IOException e) {
                        logger.error("关闭输出流失败: {}", e.getMessage(), e);
                        return Mono.just(ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                                .body(null));
                    }
                });
    }

    /**
     * PPT/PPTX转PDF接口
     */
    @PostMapping(value = "/convert-powerpoint-to-pdf", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public Mono<ResponseEntity<byte[]>> convertPowerPointToPdf(@RequestPart("file") FilePart file) {
        logger.info("收到PPT/PPTX转PDF请求，文件名: {}", file.filename());

        // 使用ByteArrayOutputStream收集文件数据
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

        return file.content()
                .doOnEach(dataBufferSignal -> {
                    if (dataBufferSignal.hasValue()) {
                        DataBuffer dataBuffer = dataBufferSignal.get();
                        try {
                            // 直接将DataBuffer中的数据写入ByteArrayOutputStream
                            byteArrayOutputStream.write(dataBuffer.asByteBuffer().array());
                        } catch (IOException e) {
                            logger.error("写入文件数据失败: {}", e.getMessage(), e);
                        } finally {
                            // 释放DataBuffer
                            DataBufferUtils.release(dataBuffer);
                        }
                    }
                })
                .then(Mono.defer(() -> {
                    try {
                        byteArrayOutputStream.flush();
                        byte[] fileBytes = byteArrayOutputStream.toByteArray();
                        logger.info("成功读取文件数据，大小: {} 字节", fileBytes.length);

                        InputStream inputStream = new ByteArrayInputStream(fileBytes);
                        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

                        // 调用服务方法
                        return documentConversionService.convertPowerPointToPdf(inputStream, outputStream, file.filename())
                                .map(success -> {
                                    if (success) {
                                        byte[] pdfBytes = outputStream.toByteArray();
                                        HttpHeaders headers = new HttpHeaders();
                                        headers.setContentType(MediaType.APPLICATION_PDF);
                                        headers.setContentDispositionFormData(
                                                "attachment", getPdfFileName(file.filename()));
                                        headers.setContentLength(pdfBytes.length);

                                        return ResponseEntity.ok()
                                                .headers(headers)
                                                .body(pdfBytes);
                                    } else {
                                        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                                                .body(null);
                                    }
                                });
                    } catch (IOException e) {
                        logger.error("处理文件数据失败: {}", e.getMessage(), e);
                        return Mono.just(ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                                .body(null));
                    } finally {
                        try {
                            byteArrayOutputStream.close();
                        } catch (IOException e) {
                            logger.error("关闭输出流失败: {}", e.getMessage(), e);
                        }
                    }
                }));
    }

    /**
     * 获取PDF文件名
     */
    private String getPdfFileName(String originalFileName) {
        if (originalFileName.toLowerCase().endsWith(".docx")) {
            return originalFileName.substring(0, originalFileName.length() - 5) + ".pdf";
        } else if (originalFileName.toLowerCase().endsWith(".doc")) {
            return originalFileName.substring(0, originalFileName.length() - 4) + ".pdf";
        } else if (originalFileName.toLowerCase().endsWith(".pptx")) {
            return originalFileName.substring(0, originalFileName.length() - 5) + ".pdf";
        } else if (originalFileName.toLowerCase().endsWith(".ppt")) {
            return originalFileName.substring(0, originalFileName.length() - 4) + ".pdf";
        } else {
            return originalFileName + ".pdf";
        }
    }

    /**
     * 文本转换为文档接口
     */
    @PostMapping(value = "/text-convert", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public Mono<ResponseEntity<byte[]>> convertTextToDocument(
            @RequestPart("title") Mono<String> titleMono,
            @RequestPart("format") Mono<String> formatMono,
            @RequestPart("content") Mono<String> contentMono) {
        
        return Mono.zip(titleMono, formatMono, contentMono)
            .flatMap(tuple -> {
                String title = tuple.getT1();
                String format = tuple.getT2();
                String content = tuple.getT3();
                
                logger.info("收到文本转文档请求，标题: {}, 格式: {}", title, format);

                try {
                    // 根据格式调用不同的转换服务
                    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                    boolean success = true;
                    String contentType = "application/octet-stream";
                    String extension = "";

                    try {
                        if ("pdf".equalsIgnoreCase(format)) {
                            success = convertTextToPdf(content, outputStream, title);
                            contentType = MediaType.APPLICATION_PDF_VALUE;
                            extension = ".pdf";
                        } else if ("word".equalsIgnoreCase(format)) {
                            // 模拟Word转换
                            success = true;
                            outputStream.write(("Word文档内容：\n标题: " + title + "\n\n" + content).getBytes());
                            contentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
                            extension = ".docx";
                        } else if ("ppt".equalsIgnoreCase(format) || "pptx".equalsIgnoreCase(format)) {
                            // 模拟PPT转换
                            success = true;
                            outputStream.write(("PPT内容：\n标题: " + title + "\n\n" + content).getBytes());
                            contentType = "application/vnd.openxmlformats-officedocument.presentationml.presentation";
                            extension = ".pptx";
                        }
                    } catch (IOException e) {
                        logger.error("文本转文档失败: {}", e.getMessage(), e);
                        return Mono.just(ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null));
                    }

                    if (success) {
                        byte[] documentBytes = outputStream.toByteArray();
                        HttpHeaders headers = new HttpHeaders();
                        headers.setContentType(MediaType.parseMediaType(contentType));
                        
                        // 生成文件名
                        String timestamp = String.valueOf(System.currentTimeMillis());
                        String filename = String.format("%s_%s%s", title.replaceAll("\\s+", "_"), timestamp, extension);
                        headers.setContentDispositionFormData("attachment", filename);
                        headers.setContentLength(documentBytes.length);

                        return Mono.just(ResponseEntity.ok().headers(headers).body(documentBytes));
                    } else {
                        return Mono.just(ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null));
                    }
                } catch (Exception e) {
                    logger.error("文本转文档失败: {}", e.getMessage(), e);
                    return Mono.just(ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null));
                }
            });
    }

    /**
     * 将文本内容转换为PDF
     */
    private boolean convertTextToPdf(String content, OutputStream outputStream, String title) {
        try {
            // 使用Apache PDFBox创建PDF
            org.apache.pdfbox.pdmodel.PDDocument document = new org.apache.pdfbox.pdmodel.PDDocument();
            org.apache.pdfbox.pdmodel.PDPage page = new org.apache.pdfbox.pdmodel.PDPage();
            document.addPage(page);
            
            // 创建内容流
            org.apache.pdfbox.pdmodel.PDPageContentStream contentStream = new org.apache.pdfbox.pdmodel.PDPageContentStream(document, page);
            
            // 设置支持中文的字体
            org.apache.pdfbox.pdmodel.font.PDType0Font font = null;
            try {
                // 尝试加载系统中的中文字体
                // 这里使用通用的中文字体名称，系统会自动查找可用的字体
                String[] fontPaths = {
                    // Mac系统中的中文字体路径
                    System.getProperty("user.home") + "/Library/Fonts/SimHei.ttf",
                    System.getProperty("user.home") + "/Library/Fonts/Microsoft YaHei.ttf",
                    // Windows系统中的中文字体路径
                    "C:/Windows/Fonts/simhei.ttf",
                    "C:/Windows/Fonts/msyh.ttc",
                    // Linux系统中的中文字体路径
                    "/usr/share/fonts/truetype/wqy/wqy-microhei.ttc"
                };
                
                for (String fontPath : fontPaths) {
                    java.io.File fontFile = new java.io.File(fontPath);
                    if (fontFile.exists()) {
                        font = org.apache.pdfbox.pdmodel.font.PDType0Font.load(document, fontFile);
                        break;
                    }
                }
                
                // 如果没有找到系统中的中文字体，使用PDFBox内置的支持中文的字体
                if (font == null) {
                    // 使用支持中文的字体族
                    font = org.apache.pdfbox.pdmodel.font.PDType0Font.load(document, 
                        getClass().getResourceAsStream("/org/apache/pdfbox/resources/ttf/LiberationSans-Regular.ttf"));
                }
            } catch (Exception e) {
                logger.warn("加载中文字体失败，使用默认字体: {}", e.getMessage());
                // 如果加载失败，回退到默认字体
                font = org.apache.pdfbox.pdmodel.font.PDType0Font.load(document, 
                    getClass().getResourceAsStream("/org/apache/pdfbox/resources/ttf/LiberationSans-Regular.ttf"));
            }
            
            // 添加标题
            contentStream.beginText();
            contentStream.newLineAtOffset(50, 750);
            contentStream.setFont(font, 18);
            contentStream.showText(title);
            contentStream.endText();
            
            // 添加内容
            contentStream.beginText();
            contentStream.newLineAtOffset(50, 720);
            contentStream.setFont(font, 12);
            
            // 处理长文本，自动换行
            float yPosition = 720;
            float lineHeight = 15;
            float pageWidth = page.getMediaBox().getWidth() - 100; // 左右边距各50
            
            // 简单的文本分割逻辑
            String[] lines = content.split("\\n");
            for (String line : lines) {
                List<String> wrappedLines = new ArrayList<>();
                StringBuilder currentLine = new StringBuilder();
                String[] words = line.split("\\s+");
                
                for (String word : words) {
                    String testLine = currentLine.toString() + (currentLine.length() > 0 ? " " : "") + word;
                    float textWidth = font.getStringWidth(testLine) / 1000 * 12; // 12是字体大小
                    
                    if (textWidth > pageWidth) {
                        if (currentLine.length() > 0) {
                            wrappedLines.add(currentLine.toString());
                            currentLine = new StringBuilder(word);
                        } else {
                            // 单个单词太长，直接添加
                            wrappedLines.add(word);
                        }
                    } else {
                        if (currentLine.length() > 0) {
                            currentLine.append(" ");
                        }
                        currentLine.append(word);
                    }
                }
                
                if (currentLine.length() > 0) {
                    wrappedLines.add(currentLine.toString());
                }
                
                // 写入换行后的文本
                for (String wrappedLine : wrappedLines) {
                    if (yPosition < 50) { // 底部边距
                        // 创建新页面
                        contentStream.close();
                    page = new org.apache.pdfbox.pdmodel.PDPage();
                    document.addPage(page);
                    contentStream = new org.apache.pdfbox.pdmodel.PDPageContentStream(document, page);
                    contentStream.setFont(font, 12);
                        yPosition = 750;
                    }
                    
                    contentStream.beginText();
                    contentStream.newLineAtOffset(50, yPosition);
                    contentStream.showText(wrappedLine);
                    contentStream.endText();
                    yPosition -= lineHeight;
                }
            }
            
            // 关闭内容流
            contentStream.close();
            
            // 保存PDF到输出流
            document.save(outputStream);
            document.close();
            
            return true;
        } catch (Exception e) {
            logger.error("文本转PDF失败: {}", e.getMessage(), e);
            return false;
        }
    }
}